from django.shortcuts import render
from django.views import View
from django_redis import get_redis_connection
from utility.views import LoginRequiredJsonMixin
from apps.goods.models import SKU, SPU
from apps.users.models import Address, User
from django import http
import json, time
from apps.orders.models import OrderInfo, OrderGoods
from django.utils import timezone
from decimal import Decimal
from django.db import transaction


# Create your views here.

# 提交订单
class OrdersCommitView(LoginRequiredJsonMixin, View):

    def post(self, request):
        json_dict = json.loads(request.body.decode())
        address_id = json_dict.get('address_id')
        pay_method = json_dict.get('pay_method')

        if not all([address_id, pay_method]):
            return http.JsonResponse({'code': 400, 'errmsg': '缺少必须参数'})
        if not Address.objects.get(id=address_id):
            return http.JsonResponse({'code': 400, 'errmsg': 'address_id有误'})
        if pay_method not in [OrderInfo.PAY_METHODS_ENUM['CASH'], OrderInfo.PAY_METHODS_ENUM['ALIPAY']]:
            return http.JsonResponse({'code': 400, 'errmsg': 'pay_method有误'})

        user = request.user
        order_id = timezone.localtime().strftime('%Y%m%d%H%M%S') + ('%09d' % user.id)
        # 创建事务

        with transaction.atomic():
            # 创建保存点
            save_id = transaction.savepoint()
            try:
                orderinfo = OrderInfo.objects.create(
                    order_id=order_id,
                    user=user,
                    address=Address.objects.get(id=address_id),
                    total_count=0,
                    total_amount=0,
                    freight=Decimal(10.00),
                    pay_method=pay_method,
                    status=OrderInfo.ORDER_STATUS_ENUM['UNPAID'] if pay_method == OrderInfo.PAY_METHODS_ENUM[
                        'ALIPAY'] else
                    OrderInfo.ORDER_STATUS_ENUM['UNSEND']
                )

                # 保存订单商品
                user = request.user
                redis_conn = get_redis_connection('carts_code')

                redis_set = redis_conn.smembers('selected_%s' % user.id)
                redis_dict = redis_conn.hgetall('carts_%s' % user.id)
                sku_id_dict = {}
                for sku_id, count in redis_dict.items():
                    if sku_id in redis_set:
                        sku_id_dict[int(sku_id)] = int(count)

                for order_sku_id in sku_id_dict.keys():
                    while True:
                        sku = SKU.objects.get(id=order_sku_id)

                        save_stock = sku.stock
                        save_sales = sku.sales
                        # import time
                        # time.sleep(5)
                        if sku_id_dict[order_sku_id] > sku.stock:
                            transaction.savepoint_rollback(save_id)
                            return http.JsonResponse({'code': 400, 'errmsg': '库存不足'})

                        # sku.stock -= sku_id_dict[order_sku_id]
                        # sku.sales += sku_id_dict[order_sku_id]
                        # sku.save()
                        result = SKU.objects.filter(id=sku.id, stock=save_stock).update(
                            stock=save_stock - sku_id_dict[order_sku_id],
                            sales=save_sales + sku_id_dict[order_sku_id]
                        )
                        # print(type(result))
                        if not result:
                            continue

                        sku.spu.sales += sku_id_dict[order_sku_id]
                        sku.spu.save()
                        OrderGoods.objects.create(
                            order=OrderInfo.objects.get(order_id=order_id),
                            sku=sku,
                            count=sku_id_dict[order_sku_id],
                            price=sku.price,
                        )
                        orderinfo.total_count += sku_id_dict[order_sku_id]
                        orderinfo.total_amount += sku_id_dict[order_sku_id] * sku.price
                        break
                    orderinfo.total_amount += orderinfo.freight
                    orderinfo.save()
            except Exception as e:
                transaction.savepoint_rollback(save_id)
                return http.JsonResponse({'code': 400, 'errmsg': '下单失败'})

            transaction.savepoint_commit(save_id)

            # 删除购物车
            pl = redis_conn.pipeline()
            pl.hdel('carts_%s' % user.id, *redis_set)
            pl.srem('selected_%s' % user.id, *redis_set)
            pl.execute()

            return http.JsonResponse({'code': 0, 'errmsg': 'ok', 'order_id': order_id})


# 结算订单
class SettlementView(LoginRequiredJsonMixin,View):

    def get(self, request):



        user_id = request.user.id
        user = User.objects.get(id=user_id)
        # 获取用户地址
        address_list = []
        addresses = Address.objects.filter(user_id=user_id, is_deleted=False)
        for address in addresses:
            address_list.append({
                "id": address.id,
                "province": address.province.name,
                "city": address.city.name,
                "district": address.district.name,
                "place": address.place,
                "mobile": address.mobile,
                "receiver": address.receiver,
            })
        redis_conn = get_redis_connection('carts_code')
        # pl = redis_conn.pipeline()
        # pl = redis_conn.pipeline()
        redis_set = redis_conn.smembers('selected_%s' % user_id)
        redis_dict = redis_conn.hgetall('carts_%s' % user_id)

        # 获取商品数据库中商品信息
        skus = []
        for sku_id, count in redis_dict.items():
            if sku_id in redis_set:
                sku = SKU.objects.get(id=int(sku_id))
                skus.append({
                    "id": sku.id,
                    "name": sku.name,
                    "default_image_url": sku.default_image.url,
                    "count": int(count),
                    "price": sku.price,
                })
        context = {
            'addresses': address_list,
            'skus': skus,
            'freight': Decimal(10.00)
        }

        return http.JsonResponse({'code': 0, 'errmsg': 'ok', 'context': context})
        # else:
        #     return http.JsonResponse({'code': 401, 'errmsg': 'ok'})
